import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import React, { Component } from 'react';

import { ScrollView, View } from '@/cross/components';
import './PutSuperType.scss';

import { AutoForm, Button, HeaderBar, Page, TabItem } from '@/cross/components';

import { CrossPageProps } from '@/cross/pages/PropType';
import authStore from '@/cross/stores/auth';
import { $message, $preload } from '@/cross/utils';
import { EditorStore } from '@/pages/editor/store/page';
import { validateJsCode } from '@/pages/editor/utils/ast/validateJscode';
import { checkActionIsLifeCycle } from '@/pages/editor/utils/checkActionIsLifeCycle';
import { getLifeCycles, lifeCycleCodeTemplate } from '@/pages/editor/utils/getLifeCycles';
import classNames from 'classnames';
import { ApiTool } from '../../../../components/superType/ApiTool/ApiTool';
import { JsonEditor } from '../../../../components/superType/CodeEditor/JsonEditor';
import { createTypeFieldForm } from '../../../../components/superType/FormWidget/TypeEditor';
import { ActionEditor } from '../../../../components/superType/FunctionEditor/ActionEditor';
import { ActionInfo } from '../../../../components/superType/FunctionEditor/ActionInfo';
import typeStore from '../../../../pages/editor/store/type.store';
import { ITypeEntity } from '../types';
import { checkFieldIsUnique } from '../utils/checkFieldIsUnique';
import { ActionParams } from '@/components/superType/FunctionEditor/ActionParams';

interface IProps extends CrossPageProps {
  // store?: EditorStore;
  inMainTab?: boolean;
  tabKey?: string;
  params: {
    fkId?: string;
    fileName?: string;
    folder?: string;
    projectId?: string;
    type?: ITypeEntity['type'];
    item?: ITypeEntity;
    copy?: boolean;
    extendNewType?: Partial<ITypeEntity>;
    onSave?: (typeItem: ITypeEntity) => void;
    onInit?: (ref: TypeEditor) => void;

    /**
     * 嵌入存储type时使用（不单独存types库）
     */
    onChange?: (item: ITypeEntity) => void;
  };
}

@observer
class TypeEditor extends Component<IProps> {
  autoFormRef = React.createRef<AutoForm<ITypeEntity>>();
  actionEditor = React.createRef<ActionEditor>();
  @observable formValue: ITypeEntity = {
    name: '',
    desc: '',
    type: 'vo',
    fields: [],
  };
  @observable inited = false;

  componentDidMount() {
    const { type, fkId, projectId, fileName, folder, copy, item, extendNewType, onInit } =
      this.props.params;
    // 动作编辑默认Tab为动作编辑
    if ((item?.type || type) !== 'action') {
      this.tab = 'type-doc';
    }
    if (item) {
      this.formValue = {
        ...item,
        ...(copy
          ? {
              _id: undefined,
              name: '',
              desc: '',
            }
          : {}),
      };
    } else {
      if (['api', 'action', 'api-import', 'vo', 'config'].includes(type)) {
        const data: ITypeEntity = {
          name: ['config'].includes(type) ? type : '',
          desc: ['config'].includes(type) ? type : '',
          type,
          fkId,
          fileName,
          folder,
          projectId,
          params: [],
          fields: [],
          ...(type === 'action'
            ? {
                code: {
                  type: 'JSFunction',
                  value: 'function() {\n\n}',
                },
              }
            : {}),
          ...extendNewType,
        };
        this.formValue = data;
      }
    }
    this.inited = true;
    if (!this.props.inMainTab) {
      $preload('onEnterSave', this.save);
    }
    onInit?.(this);
  }

  onFinish: () => void;
  save = (finish) => {
    this.onFinish = finish;
    this.submit(true);
  };

  componentWillUnmount(): void {
    if (!this.props.inMainTab) $preload('onEnterSave', null);
  }

  @observable tab:
    | 'type-doc'
    | 'api-debug'
    | 'data-edit'
    | 'action-edit'
    | 'action-info'
    | 'action-params' = 'action-edit';
  @action changeTab = (tab: typeof this.tab) => {
    this.tab = tab;
  };

  // @computed get currentDataValue() {
  //   const {
  //     params: { fkId },
  //     store,
  //   } = this.props;
  // const { dataStore, globalStore } = store.emuStore;
  // const typeIsGlobalData = fkId === String(authStore.currentRole.shop_id);
  // return typeIsGlobalData
  //   ? (globalStore?.data as IPublicTypeJSONValue)
  //   : (dataStore?.data as IPublicTypeJSONValue);
  // }

  onDataToolChange = (value) => {
    const {
      params: { fkId },
      // store,
    } = this.props;
    // const { dataStore, globalStore } = store.emuStore; @TODO: 数据存储位置需要调整
    const typeIsGlobalData = fkId === String(authStore.currentRole.shop_id);
    if (typeIsGlobalData) {
      // globalStore.data = value;
    } else {
      // dataStore.data = value;
    }
  };

  onChange = (value: ITypeEntity, ...args) => {
    this.formValue = value;
  };

  onActionEditorChange = async (values: Partial<ITypeEntity>) => {
    // 设置声明周期后自动命名
    // console.log('[values.name] ', values.name);
    // console.log('[isLifeCycle] ', values?.name ? checkActionIsLifeCycle(values?.name) : '');
    const fileName = this.formValue.fileName;
    if (
      typeof values.lifeCycle !== 'undefined' &&
      (!values.name || checkActionIsLifeCycle(values?.name))
    ) {
      values.name = values.lifeCycle;
      values.desc = values.lifeCycle
        ? getLifeCycles(!fileName).find((item) => item.value === values.lifeCycle)?.label
        : '';

      setTimeout(() => {
        this.actionEditor?.current?.onActionNameBlur({
          template: lifeCycleCodeTemplate[values.lifeCycle],
        });
      }, 300);
    }
    this.formValue = {
      ...this.formValue,
      ...values,
    };
  };

  submit = (willClose?: boolean) => {
    const { copy, onSave, onChange } = this.props.params;
    const form = this.autoFormRef.current?.form;
    form
      ?.validate()
      .then(async () => {
        // 通过移除主键实现复制
        if (copy) delete this.formValue._id;
        const { _id, type, fileName, name, fields, params, pathParams, headers, query, code } =
          this.formValue;
        // 是否是编辑
        const isEditAction = !!this.props.params.item?.name;
        if (!isEditAction) {
          // 判断类型名称是否重复
          if (type === 'action') {
            const actionType = typeStore.getActionType(fileName, name);
            if (actionType) return $message.error('动作标识 ' + name + ' 已存在');
          }
        }
        // 判断是否有重复的字段
        if (!checkFieldIsUnique(fields)) return $message.error('请移除重复的字段名');
        if (!checkFieldIsUnique(params)) return $message.error('请移除重复的字段名');
        if (!checkFieldIsUnique(pathParams)) return $message.error('请移除重复的字段名');
        if (!checkFieldIsUnique(headers)) return $message.error('请移除重复的字段名');
        if (!checkFieldIsUnique(query)) return $message.error('请移除重复的字段名');

        // 校验代码
        if (type === 'action') {
          try {
            await validateJsCode(code, {
              fileName,
            });
          } catch (err) {
            return;
          }
        }

        typeStore
          .saveType(
            {
              ...this.formValue,
            },
            {
              isEditAction,
              prevVersionValue: this.props.params.item,
              delay: onSave ? 1000 : 1000,
            },
          )
          .then(async (type) => {
            if (!willClose) this.formValue = type;
            // 回调
            onSave?.(type);

            this.onFinish?.();

            if (willClose) {
              this.props.navigation && this.props.navigation.goBack();
            }
          })
          .catch((e) => {
            // console.log('[e] ', e);
            if (e && (e.errmsg || e.response?.data?.message))
              $message.error(e.errmsg || e.response?.data?.message);
          });
      })
      .catch((e) => {
        console.log('[e] ', e);
        if (e && e.message) {
          $message.error(e.message);
        }
      });
  };

  render() {
    const { inMainTab } = this.props;
    const { type, item, copy } = this.props.params;
    const _type = type || item?.type;
    const typeNameMap = {
      api: '接口',
      action: '动作',
      type: '类型',
      config: '参数配置',
      'api-import': '接口文档',
    };
    const typeName = typeNameMap[_type] || '类型';

    const bottomContent = ['data', 'api', 'action'].includes(_type) && (
      <View className="M-flexbox-horizontal M-p-t-5 M-p-l-10">
        {_type === 'action' && (
          <React.Fragment>
            <TabItem
              title="函数编辑"
              active={this.tab === 'action-edit'}
              onClick={this.changeTab.bind(this, 'action-edit')}
            />
            <TabItem
              title="动作参数"
              active={this.tab === 'action-params'}
              onClick={this.changeTab.bind(this, 'action-params')}
            />
          </React.Fragment>
        )}
        {_type !== 'action' && (
          <TabItem
            title={_type === 'data' ? '数据模型' : '接口文档'}
            active={this.tab === 'type-doc'}
            onClick={this.changeTab.bind(this, 'type-doc')}
          />
        )}
        {_type === 'api' && (
          <TabItem
            title="接口调试"
            active={this.tab === 'api-debug'}
            onClick={this.changeTab.bind(this, 'api-debug')}
          />
        )}
        {_type === 'action' && (
          <TabItem
            title="动作设置"
            active={this.tab === 'action-info'}
            onClick={this.changeTab.bind(this, 'action-info')}
          />
        )}
        {/* {_type === 'data' && (
          <TabItem
            title="数据编辑"
            active={this.tab === 'data-edit'}
            onClick={this.changeTab.bind(this, 'data-edit')}
          />
        )} */}
      </View>
    );

    return (
      <Page className="put-super-type dark-editor" {...this.props}>
        {inMainTab ? (
          <div style={{ background: '#2b2b2b' }}>{bottomContent}</div>
        ) : (
          <HeaderBar
            title={`${copy ? '复制' : item ? '编辑' : '新建'}${typeName}`}
            titleAlign="left"
            mode="dark"
            leftContent={null}
            showBack
            backgroundColor="#353535"
            rightContent={
              <View className="M-flexbox-horizontal M-horizontal-right M-p-r-10">
                <Button onClick={this.props.navigation?.goBack} color="gray" className="M-m-r-8">
                  取消
                </Button>
                <Button onClick={() => this.submit(true)}>保存</Button>
              </View>
            }
            bottomContent={bottomContent}
          />
        )}
        <ScrollView
          className={classNames({
            'M-display-none': this.tab !== 'type-doc',
          })}
          style={{ backgroundColor: '#3e3e3e' }}
        >
          <View className="M-p-h-b-20 M-p-b-10">
            <View className="M-p-t-10">
              {/* <FormSchemaEditor ref={(node) => (this.editorRef = node)} value={'' as any} onChange={this.onChange} /> */}
              <AutoForm<ITypeEntity>
                ref={this.autoFormRef}
                theme="dark"
                config={{
                  rule: {
                    name: [
                      {
                        required: true,
                        message: '请输入',
                        enable: (values) => !['api', 'api-import'].includes(values.type),
                      },
                      {
                        type: 'regexp',
                        pattern: /^([^\x00-\xff]|[a-zA-Z_$])([^\x00-\xff]|[a-zA-Z0-9_$])*$/,
                        message: '仅可输入英文、数字、下划线',
                        enable: (values) => !['api', 'api-import'].includes(values.type),
                      },
                    ],
                  },
                  fields: [
                    {
                      widget: 'item-rows',
                      labelProps: {},
                      field: 'desc',
                      widgetProps: {
                        gutter: [10, 10],
                      },
                      childs: [
                        {
                          viewProps: { span: 6 },
                          params: {
                            type: 'string',
                            field: 'name',
                            widget: 'text',
                            label: '类型标识',
                            labelProps: { required: true },
                            widgetProps: { placeholder: '类型标识推荐大写开头驼峰命名法' },
                            display: (values) =>
                              !['data', 'api', 'action', 'api-import', 'config'].includes(
                                values.type,
                              ),
                          },
                        },
                        {
                          viewProps: { span: 4 },
                          params: {
                            type: 'string',
                            field: 'desc',
                            widget: 'text',
                            label: '类型名称',
                            display: (values) =>
                              !['data', 'api', 'action', 'api-import', 'config'].includes(
                                values.type,
                              ),
                            widgetProps: { placeholder: '类型描述将会用户生成代码的注释' },
                          },
                        },
                      ],
                    },

                    // 接口文档
                    {
                      type: 'string',
                      field: 'desc',
                      widget: 'text',
                      label: '接口文档名称',
                      labelProps: { required: true },
                      display: (values) => ['api-import'].includes(values.type),
                      widgetProps: { placeholder: '请输入接口文档名称' },
                    },
                    // {
                    //   type: 'string',
                    //   field: 'apiDocUrl',
                    //   widget: 'text',
                    //   label: '文档地址（目前仅支持 openapi 文档）',
                    //   display: (values) => ['api-import'].includes(values.type),
                    //   widgetProps: { placeholder: '请输入接口文档地址' },
                    // },
                    {
                      type: 'string',
                      field: 'host',
                      widget: 'text',
                      label: '域名',
                      display: (values) => ['api-import'].includes(values.type),
                      widgetProps: { placeholder: 'http://www.xxx.com' },
                    },
                    {
                      type: 'string',
                      field: 'hostConstantName',
                      widget: 'text',
                      label: '域名映射全局变量名',
                      labelProps: {
                        required: true,
                      },
                      help: '自动创建全局变量，方便全局更改接口域名',
                      display: (values) => ['api-import'].includes(values.type),
                      widgetProps: { placeholder: '建议 HostDomain 请注意不要重复' },
                    },
                    {
                      type: 'string',
                      field: 'basePath',
                      widget: 'text',
                      label: '接口路径前缀',
                      display: (values) => ['api-import'].includes(values.type),
                      widgetProps: { placeholder: '/backend' },
                    },
                    {
                      type: 'string',
                      field: 'desc',
                      widget: 'text',
                      label: '接口名称',
                      labelProps: { required: true },
                      display: (values) => values.type === 'api',
                      widgetProps: { placeholder: '请输入接口名称' },
                    },
                    {
                      type: 'string',
                      field: 'uri',
                      widget: 'text',
                      label: '接口URL',
                      labelProps: { required: true },
                      display: (values) => values.type === 'api',
                      widgetProps: { placeholder: '请输入接口地址' },
                    },
                    {
                      type: 'string',
                      field: 'method',
                      widget: 'select',
                      label: '调用方法',
                      labelProps: { required: true },
                      display: (values) => values.type === 'api',
                      f_options: [
                        { label: 'POST', value: 'POST' },
                        { label: 'GET', value: 'GET' },
                        { label: 'PUT', value: 'PUT' },
                        { label: 'DELETE', value: 'DELETE' },
                      ],
                      widgetProps: { placeholder: '请输入调用方法' },
                    },
                    {
                      type: 'string',
                      field: 'contentType',
                      widget: 'select',
                      label: 'Body类型',
                      display: (values) => values.type === 'api',
                      f_options: [
                        { label: 'JSON', value: 'JSON' },
                        { label: 'FORM', value: 'FORM' },
                        { label: 'XML', value: 'XML' },
                        { label: 'RAW', value: 'RAW' },
                      ],
                      widgetProps: { placeholder: '请输入调用方法' },
                    },
                    {
                      display: (values) => values.type === 'api',
                      widget: 'auto-array-form',
                      field: 'headers',
                      label: 'Header',
                      widgetProps: {
                        keyExtractor: (row) => row.__uuid,
                        addButtonText: (
                          <Button size="small" color="gray">
                            添加参数
                          </Button>
                        ),
                        showDragHelp: false,
                      },
                      form: createTypeFieldForm(_type, undefined, this),
                    },
                    {
                      display: (values) => ['api', 'action'].includes(values.type),
                      widget: 'auto-array-form',
                      field: 'params',
                      label: (values) => (values.type === 'action' ? '输入参数' : 'Body参数'),
                      widgetProps: {
                        keyExtractor: (row) => row.__uuid,
                        addButtonText: (
                          <Button size="small" color="gray">
                            添加参数
                          </Button>
                        ),
                        showDragHelp: false,
                      },
                      form: createTypeFieldForm(_type, undefined, this),
                    },
                    {
                      display: (values) => values.type === 'api',
                      widget: 'auto-array-form',
                      field: 'query',
                      label: 'Query参数',
                      widgetProps: {
                        keyExtractor: (row) => row.__uuid,
                        addButtonText: (
                          <Button size="small" color="gray">
                            添加参数
                          </Button>
                        ),
                        showDragHelp: false,
                      },
                      form: createTypeFieldForm(_type, undefined, this),
                    },
                    {
                      display: (values) => values.type === 'api',
                      widget: 'auto-array-form',
                      field: 'pathParams',
                      label: 'Path参数',
                      widgetProps: {
                        keyExtractor: (row) => row.__uuid,
                        addButtonText: (
                          <Button size="small" color="gray">
                            添加参数
                          </Button>
                        ),
                        showDragHelp: false,
                      },
                      form: createTypeFieldForm(_type, undefined, this),
                    },
                    {
                      widget: 'auto-array-form',
                      field: 'fields',
                      label: (values) => (values.type === 'action' ? '输出参数' : '字段'),
                      display: (values) => !['api-import', 'api'].includes(values.type),
                      widgetProps: {
                        keyExtractor: (row) => {
                          return row.__uuid;
                        },
                        addButtonText: (
                          <Button size="small" color="gray">
                            添加字段
                          </Button>
                        ),
                        showDragHelp: false,
                      },
                      form: createTypeFieldForm(_type, undefined, this),
                    },
                    {
                      widget: 'auto-array-form',
                      field: 'fields',
                      label: '返回响应',
                      display: (values) => ['api'].includes(values.type),
                      default: {
                        name: '200',
                      },
                      widgetProps: {
                        keyExtractor: (row) => row.__uuid,
                        addButtonText: (
                          <Button size="small" color="gray">
                            添加响应
                          </Button>
                        ),
                        showDragHelp: false,
                      },
                      form: createTypeFieldForm(_type, 'api-response', this),
                    },
                  ],
                }}
                value={this.formValue}
                onChange={this.onChange}
              />
            </View>
          </View>
          <View className="M-p-t-5" />
          {this.formValue.type === 'api-import' && (
            <View className="M-p-h-b-20">
              <View className="M-f-c-fff M-f-s-14 M-p-b-10">文档JSON（粘贴openapi文档）</View>
              <JsonEditor
                value={this.formValue.apiDocStr ? JSON.parse(this.formValue.apiDocStr) : undefined}
                onChange={(v) => {
                  this.onActionEditorChange({
                    apiDocStr: JSON.stringify(v),
                  });
                }}
              />
            </View>
          )}
        </ScrollView>
        {/* 接口调试 */}
        <ScrollView
          className={classNames({
            'M-display-none': this.tab !== 'api-debug',
          })}
          style={{ backgroundColor: '#3e3e3e' }}
        >
          <View className="M-p-h-b-20 M-p-t-15 M-p-b-10">
            {_type === 'api' && this.tab === 'api-debug' && (
              <ApiTool mode="api-debug" tabKey={this.props.tabKey} schema={this.formValue} />
            )}
          </View>
          <View className="M-p-t-5" />
        </ScrollView>
        {/* 动作设置 */}
        <ScrollView
          className={classNames({
            'M-display-none': this.tab !== 'action-info',
          })}
          style={{ backgroundColor: '#3e3e3e' }}
        >
          <View className="M-p-h-b-20 M-p-v-b-15">
            {this.inited && (
              <ActionInfo
                value={this.formValue}
                onChange={(v) => {
                  this.onActionEditorChange(v);
                }}
              />
            )}
          </View>
          {/* <View className="M-p-t-5" /> */}
        </ScrollView>
        {/* 数据编辑 */}
        <ScrollView
          className={classNames({
            'M-display-none': this.tab !== 'data-edit',
          })}
          style={{ backgroundColor: '#3e3e3e' }}
        >
          <View className="M-p-h-b-20 M-p-b-10">
            {/* {_type === 'data' && (
              <DataTool
                mode="api-debug"
                schema={this.formValue}
                value={this.currentDataValue}
                onChange={this.onDataToolChange}
              />
            )} */}
          </View>
          <View className="M-p-t-5" />
        </ScrollView>
        <ScrollView
          className={classNames({
            'M-display-none': this.tab !== 'data-edit',
          })}
          style={{ backgroundColor: '#3e3e3e' }}
        >
          <View className="M-p-h-b-20 M-p-b-10">
            {/* {_type === 'data' && (
              <DataTool
                mode="api-debug"
                schema={this.formValue}
                value={this.currentDataValue}
                onChange={this.onDataToolChange}
              />
            )} */}
          </View>
          <View className="M-p-t-5" />
        </ScrollView>
        {/* 函数编辑 */}
        {_type === 'action' && (
          <React.Fragment>
            <View
              className={classNames('M-flex-item', 'M-flexbox-vertical', {
                'M-display-none': this.tab !== 'action-edit',
              })}
              style={{ backgroundColor: '#3e3e3e' }}
            >
              <ActionEditor
                ref={this.actionEditor}
                value={this.formValue}
                onEnterSave={() => this.submit(true)}
                onChange={this.onActionEditorChange}
              />
            </View>
            <View
              className={classNames('M-flex-item', 'M-flexbox-vertical', {
                'M-display-none': this.tab !== 'action-params',
              })}
              style={{ backgroundColor: '#3e3e3e' }}
            >
              <ActionParams onChange={this.onActionEditorChange} />
            </View>
          </React.Fragment>
        )}
      </Page>
    );
  }
}

export default TypeEditor;
